use std::fmt::{Debug, Formatter};
use futures::channel::mpsc::Receiver;
use crate::{define, os};
pub use crate::define::{
    UsbError, ControlTransferRequest,UsbControlRecipient,
    UsbControlTransferType, OsManager,Device,MResult
};


pub struct  UsbManager{
    os: Box<dyn OsManager>
}

pub struct  UsbDevice{
    ctx: Box<dyn Device>
}

impl Debug for UsbDevice{
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "[{}] vid={}, pid={}",self.ctx.get_name(), self.ctx.get_vid(), self.ctx.get_pid())
    }
}

impl UsbDevice{
    fn new(ctx: Box<dyn Device>)->Self{
        Self{
            ctx
        }
    }

    pub fn get_name(&self)->String{
        self.ctx.get_name()
    }

    pub fn get_vid(&self)->u64{
        self.ctx.get_vid()
    }

    pub fn get_pid(&self)->u64{
        self.ctx.get_pid()
    }

    pub async fn open(&mut self)-> MResult<()>{
        self.ctx.open().await
    }
    pub async fn control_transfer_in(&self, request: ControlTransferRequest)-> MResult<Vec<u8>>{
        self.ctx.control_transfer_in(request).await
    }
    pub async fn control_transfer_out(&self, request: ControlTransferRequest)-> MResult<usize>{
        self.ctx.control_transfer_out(request).await
    }

    pub fn interfaces(&self)-> MResult<Vec<UsbInterface>>{
        let len = self.ctx.interface_count()?;
        let mut out = vec![];
        for i in 0..len {
            out.push( UsbInterface::new(self.ctx.interface_get(i)?));
        }
        Ok(out)
    }

    pub fn default_interface(&self)-> MResult<UsbInterface>{
        Ok(UsbInterface::new(self.ctx.interface_default()?))
    }
}

pub struct UsbInterface{
    ctx: Box<dyn define::UsbInterface>
}

impl UsbInterface {
    fn new(ctx: Box<dyn define::UsbInterface>)->Self{
        Self{
            ctx
        }
    }
    pub fn number(&self)->MResult<usize>{
        self.ctx.number()
    }

    pub fn open_bulk_in_channel(&self, package_len: usize, endpoint: usize)->MResult<Receiver<Vec<u8>>>{
        self.ctx.open_bulk_in_channel(package_len, endpoint)
    }
}



impl UsbManager {
    pub fn new()-> Self{
        #[cfg(windows)]
        let os = os::windows::manager::Manager::new();
        #[cfg(unix)]
        let os = os::linux::manager::Manager::new();

        Self{
            os: Box::new(os)
        }
    }

    #[cfg(not(android))]
    pub async fn device_all(&self)-> MResult<Vec<UsbDevice>>{
        self.device_find(None, None).await
    }

    #[cfg(not(android))]
    pub async fn device_find(&self, vid: Option<u64>, pid: Option<u64>)-> MResult<Vec<UsbDevice>>{
        let list  = self.os.device_find(vid, pid).await?;
        let out = list.into_iter().map(|v|{
            UsbDevice::new(v)
        }).collect();
        Ok(out)
    }
}


